﻿using Autofac;
using Autofac.Core;
using Autofac.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace CommonDevelop.Ioc
{
    /// <summary>
    /// Ioc容器
    /// </summary>
    public class AutofacContainer
    {
        private static ContainerBuilder _builder = new ContainerBuilder();
        /// <summary>
        /// 容器
        /// </summary>
        private static IContainer _container;
        private static Dictionary<string, string> _otherAssembly = new Dictionary<string, string>();
        private static Dictionary<Type, Type> _dicTypes = new Dictionary<Type, Type>();

        /// <summary>
        /// 注册程序集
        /// </summary>
        public static void Register(string EndsWith, string assembly)
        {
            if (_container == null)
                _otherAssembly.Add(EndsWith, assembly);
        }

        /// <summary>
        /// 注册类型
        /// </summary>
        public static void Register<TInterface, TImplementation>() where TImplementation : TInterface
        {
            if (_container == null)
                _dicTypes.Add(typeof(TInterface), typeof(TImplementation));
        }

        /// <summary>
        /// 注册一个单例实体
        /// </summary>
        public static void Register<T>(T instance) where T : class
        {
            _builder.RegisterInstance(instance).SingleInstance();
        }

        /// <summary>
        /// 构建IOC容器
        /// </summary>
        public static IServiceProvider Build(IServiceCollection services = null)
        {
            if (_container != null)
                return new AutofacServiceProvider(_container);

            if (_otherAssembly != null)
                foreach (var item in _otherAssembly)
                    _builder.RegisterAssemblyTypes(Assembly.Load(item.Value))
                            .Where(t => t.Name.EndsWith(item.Key))
                            .AsImplementedInterfaces().InstancePerLifetimeScope();

            if (_dicTypes != null)
                foreach (var dicType in _dicTypes)
                    _builder.RegisterType(dicType.Value).As(dicType.Key);

            if (services != null)
                _builder.Populate(services);

            _container = _builder.Build();
            return new AutofacServiceProvider(_container);
        }

        public static T Resolve<T>()
        {
            return _container.Resolve<T>();
        }

        public static T Resolve<T>(params Parameter[] parameters)
        {
            return _container.Resolve<T>(parameters);
        }

        public static object Resolve(Type targetType)
        {
            return _container.Resolve(targetType);
        }

        public static object Resolve(Type targetType, params Parameter[] parameters)
        {
            return _container.Resolve(targetType, parameters);
        }
    }
}
